//package com.lemon.web.advice;
//
//import com.lemon.exception.base.BussinessException;
//import com.lemon.web.dto.BaseResponse;
//import com.lemon.web.util.ResponseUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.ConversionNotSupportedException;
//import org.springframework.beans.TypeMismatchException;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.core.annotation.Order;
//import org.springframework.data.rest.webmvc.ResourceNotFoundException;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.converter.HttpMessageNotReadableException;
//import org.springframework.http.converter.HttpMessageNotWritableException;
//import org.springframework.validation.BindException;
//import org.springframework.validation.BindingResult;
//import org.springframework.web.HttpMediaTypeNotAcceptableException;
//import org.springframework.web.HttpMediaTypeNotSupportedException;
//import org.springframework.web.HttpRequestMethodNotSupportedException;
//import org.springframework.web.bind.MethodArgumentNotValidException;
//import org.springframework.web.bind.MissingPathVariableException;
//import org.springframework.web.bind.MissingServletRequestParameterException;
//import org.springframework.web.bind.ServletRequestBindingException;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.ResponseBody;
//import org.springframework.web.bind.annotation.ResponseStatus;
//import org.springframework.web.bind.annotation.RestControllerAdvice;
//import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
//import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
//import org.springframework.web.multipart.support.MissingServletRequestPartException;
//import org.springframework.web.servlet.NoHandlerFoundException;
//
//import javax.servlet.http.HttpServletRequest;
//import javax.validation.ConstraintViolation;
//import javax.validation.ConstraintViolationException;
//import java.util.List;
//import java.util.Set;
//import java.util.stream.Collectors;
//
///**
// * @author lemon
// * @description 对业务中出现的 Exception 做了统一异常处理, 并根据 RESTful Api 规范返回对应的 HttpCode.
// * @date 2020-07-01 17:41
// */
//
//@Slf4j
//@Order(1)
//@RestControllerAdvice
//@ConditionalOnProperty(name="unified.exception.enabled", havingValue = "true", matchIfMissing = true)
//public class DefaultUnifiedExceptionRestControllerAdvice {
//    @Value("#{'${beforeBodyWrite.ignore.urls:/error}'.toLowerCase().split(',')}")
//    private List<String> ignoreUrls;
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:50
//     */
//    @ExceptionHandler(value = BussinessException.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
//    @ResponseBody
//    public BaseResponse bussinessExceptionHandler(HttpServletRequest request, BussinessException e) {
//        log.error(e.getMessage(), e);
//        return this.getResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param req
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:50
//     */
//    @ExceptionHandler(value = ResourceNotFoundException.class)
//    @ResponseStatus(HttpStatus.NOT_FOUND)
//    @ResponseBody
//    public BaseResponse resourceNotFoundExceptionHandler(HttpServletRequest req, ResourceNotFoundException e) {
//        String err = String.format("%s not found", req.getRequestURI());
//        log.debug(err, e);
//        return this.getResponse(String.valueOf(HttpStatus.NOT_FOUND.value()), err, null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:50
//     */
//    @ExceptionHandler(value = IllegalArgumentException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse illegalArugmentExceptionHandler(HttpServletRequest request, IllegalArgumentException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:50
//     */
//    @ExceptionHandler(value = IllegalStateException.class)
//    @ResponseStatus(HttpStatus.FORBIDDEN)
//    @ResponseBody
//    public BaseResponse illegalStateExceptionHandler(HttpServletRequest request, IllegalStateException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.FORBIDDEN.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param req
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:49
//     */
//    @ExceptionHandler(value = ConstraintViolationException.class)
//    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse constraintViolationExceptionHandler(HttpServletRequest req, ConstraintViolationException e) {
//        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
//        String errorMsg = violations.stream()
//                .map((violation) -> String.format("%s: %s", violation.getPropertyPath(), violation.getMessage()))
//                .collect(Collectors.joining("\n"));
//        log.debug(errorMsg);
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), errorMsg, null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:49
//     */
//    @ExceptionHandler(value = Exception.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
//    @ResponseBody
//    public BaseResponse exceptionHandler(HttpServletRequest request, Exception e) {
//        log.error(e.getMessage(), e);
//        return this.getResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description 参数格式和 @RequestParam 不符
//     * @author lemon
//     * @date 2020-07-06 08:45
//     */
//    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse methodArgumentTypeMismatchExceptionHandler(HttpServletRequest request, MethodArgumentTypeMismatchException e) {
//        String err = String.format("field: %s. %s", e.getName(), e.getMessage());
//        log.warn(err);
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), err, null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:22
//     */
//    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
//    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
//    @ResponseBody
//    public BaseResponse handleHttpRequestMethodNotSupported(HttpServletRequest request, HttpRequestMethodNotSupportedException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.METHOD_NOT_ALLOWED.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:23
//     */
//    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
//    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
//    @ResponseBody
//    public BaseResponse handleHttpMediaTypeNotSupported(HttpServletRequest request, HttpMediaTypeNotSupportedException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:23
//     */
//    @ExceptionHandler(value = HttpMediaTypeNotAcceptableException.class)
//    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
//    @ResponseBody
//    public BaseResponse handleHttpMediaTypeNotAcceptable(HttpServletRequest request, HttpMediaTypeNotAcceptableException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.NOT_ACCEPTABLE.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:42
//     */
//    @ExceptionHandler(value = MissingPathVariableException.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
//    @ResponseBody
//    public BaseResponse handleMissingPathVariable(HttpServletRequest request, MissingPathVariableException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description 缺少 @RequestParam 中的 required 参数
//     * @author lemon
//     * @date 2020-07-06 08:25
//     */
//    @ExceptionHandler(value = MissingServletRequestParameterException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse missingServletRequestParameterExceptionHandler(HttpServletRequest request, MissingServletRequestParameterException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:26
//     */
//    @ExceptionHandler(value = ServletRequestBindingException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse servletRequestBindingExceptionHandler(HttpServletRequest request, ServletRequestBindingException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:45
//     */
//    @ExceptionHandler(value = ConversionNotSupportedException.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
//    @ResponseBody
//    public BaseResponse handleConversionNotSupported(HttpServletRequest request, ConversionNotSupportedException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 09:21
//     */
//    @ExceptionHandler(value = TypeMismatchException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse handleTypeMismatch(HttpServletRequest request, TypeMismatchException e) {
//        String err = String.format("property name: %s, required type: %s, meggage: %s", e.getPropertyName(), e.getRequiredType(), e.getMessage());
//        log.warn(err);
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), err, null);
//    }
//
//    /**
//     * @param req
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description request body 按期望的 json 格式解析失败, 如 某个字段期望为int, 而实际给了string
//     * @author lemon
//     * @date 2020-07-06 08:46
//     */
//    @ExceptionHandler(value = HttpMessageNotReadableException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse handleHttpMessageNotReadable(HttpServletRequest req, HttpMessageNotReadableException e) {
//        String err = "Required request body is missing";
//        log.debug(err);
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), err, null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:47
//     */
//    @ExceptionHandler(value = HttpMessageNotWritableException.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
//    @ResponseBody
//    public BaseResponse handleHttpMessageNotWritable(HttpServletRequest request, HttpMessageNotWritableException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description annotation @Valid 对象中的字段验证失败
//     * @author lemon
//     * @date 2020-07-06 08:47
//     */
//    @ExceptionHandler(value = MethodArgumentNotValidException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse handleMethodArgumentNotValid(HttpServletRequest request, MethodArgumentNotValidException e) {
//        log.warn(e.getMessage());
//        return this.getArgumentCheckResponse(e, e.getBindingResult());
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:48
//     */
//    @ExceptionHandler(value = MissingServletRequestPartException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse handleMissingServletRequestPart(HttpServletRequest request, MissingServletRequestPartException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description form-data 表单中的数据格式错误
//     * @author lemon
//     * @date 2020-07-06 08:48
//     */
//    @ExceptionHandler(value = BindException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ResponseBody
//    public BaseResponse handleBindException(HttpServletRequest request, BindException e) {
//        log.warn(e.getMessage());
//        return this.getArgumentCheckResponse(e, e.getBindingResult());
//    }
//
//    /**
//     * @param req
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:49
//     */
//    @ExceptionHandler(value = NoHandlerFoundException.class)
//    @ResponseStatus(HttpStatus.NOT_FOUND)
//    @ResponseBody
//    public BaseResponse handleNoHandlerFoundException(HttpServletRequest req, NoHandlerFoundException e) {
//        String err = String.format("%s not found", req.getRequestURI());
//        log.debug(err);
//        return this.getResponse(String.valueOf(HttpStatus.NOT_FOUND.value()), err, null);
//    }
//
//    /**
//     * @param request
//     * @param e
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 08:50
//     */
//    @ExceptionHandler(value = AsyncRequestTimeoutException.class)
//    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
//    @ResponseBody
//    public BaseResponse handleAsyncRequestTimeoutException(HttpServletRequest request, AsyncRequestTimeoutException e) {
//        log.warn(e.getMessage());
//        return this.getResponse(String.valueOf(HttpStatus.SERVICE_UNAVAILABLE.value()), e.getMessage(), null);
//    }
//
//    /**
//     * @param e
//     * @param bindingResult
//     * @return com.lemon.web.dto.BaseResponse
//     * @description
//     * @author lemon
//     * @date 2020-07-06 09:35
//     */
//    public BaseResponse getArgumentCheckResponse(Exception e, BindingResult bindingResult) {
//        String errorFieldMessage = ResponseUtil.getErrorFieldMessage(e, bindingResult.getAllErrors());
//        return new BaseResponse(String.valueOf(HttpStatus.BAD_REQUEST.value()), errorFieldMessage, null);
//    }
//
//    /**
//     * @param code
//     * @param message
//     * @param data
//     * @return com.lemon.web.dto.BaseResponse
//     * @description 创建响应
//     * @author lemon
//     * @date 2020-07-06 09:32
//     */
//    private <T> BaseResponse getResponse(String code, String message, T data) {
//        return new BaseResponse(code, message, data);
//    }
//}